<template>
  <div id="app">
    <!-- 导航栏 -->
    <!-- 给左侧箭头做路由跳转，其实就是返回到用户页 -->
    <!-- 可以使用$router.back()  意思是返回到上一页 -->
    <van-nav-bar
      title="编辑资料"
      left-arrow
      @click-left="$router.back()"
    ></van-nav-bar>
    <!-- 头像区域 -->
    <div class="avatar_box">
      <van-image
        round
        width="100px"
        height="100px"
        fit="cover"
        class="avatar"
        :src="info.photo"
      />
      <van-uploader class="pic-uploader" :after-read="afterRead" />
    </div>
    <!-- 资料区域 -->
    <van-cell-group>
      <van-cell
        title="名称"
        :value="info.name"
        is-link
        @click="changeName"
      ></van-cell>
      <!-- 接口返回的gender数据中，1代表男，0代表女 -->
      <van-cell
        title="性别"
        :value="info.gender ? '男' : '女'"
        is-link
        @click="genderShow = true"
      ></van-cell>
      <van-cell
        title="生日"
        @click="birthdayHappy"
        :value="info.birthday"
        is-link
      ></van-cell>
    </van-cell-group>

    <!-- 弹出框--修改名字 -->
    <van-dialog
      @confirm="saveName"
      v-model="nameShow"
      title="修改名称"
      show-cancel-button
    >
      <van-field
        class="ipt"
        placeholder="请输入名称"
        ref="nameInp"
        v-model="editName"
      />
    </van-dialog>
    <!-- 弹出层--修改性别 -->
    <van-popup v-model="genderShow" position="bottom" class="pop">
      <van-nav-bar
        title="修改性别"
        left-text="取消"
        @click-left="genderShow = false"
      ></van-nav-bar>
      <van-cell @click="changeGender(1)" title="男" is-link></van-cell>
      <van-cell @click="changeGender(0)" title="女" is-link></van-cell>
    </van-popup>
    <!-- 弹出层--修改生日 -->
    <van-popup v-model="genderDay" position="bottom" class="birthday">
      <van-datetime-picker
        v-model="currentDate"
        :min-date="minDate"
        :max-date="maxDate"
        @confirm="changeBirth"
        @cancel="genderDay = false"
        type="date"
        title="选择年月日"
      />
    </van-popup>

    <!-- 图片裁剪容器 -->
    <div class="crop-box" v-if="cropShow">
      <VueCropper
        autoCrop
        autoCropWidth="165"
        autoCropHeight="165"
        ref="cropper"
        :img="cropImg"
      ></VueCropper>
      <!-- 给裁剪和取消按钮设置点击事件 -->
      <van-button @click="doCrop" type="primary">裁剪</van-button>
      <van-button @click="cropShow=false" type="primary">取消</van-button>
    </div>
  </div>
</template>

<script>
// 导入修改用户资料接口
import { editUserInfoAPI, editPhotoAPI } from '@/api/index.js'
// 导入日期插件
import moment from 'moment'
// 导入图片裁剪插件
import { VueCropper } from 'vue-cropper'
export default {
  components: {
    VueCropper
  },
  data () {
    return {
      nameShow: false,
      // 用于修改名字输入框双向绑定的变量
      editName: '',
      genderShow: false,
      genderDay: false,
      minDate: new Date(1970, 1, 1), // 最小日期
      maxDate: new Date(), // 最大日期
      currentDate: new Date(),
      cropShow: false,
      cropImg: ''
    }
  },
  methods: {
    changeName () {
      // 1. 弹出对话框
      this.nameShow = true
      // 2. 让对话框里的输入框显示当前的用户昵称
      this.editName = this.info.name
      // 3. 让输入框获得焦点
      // 利用$this.$nextTick，这是一个等下dom更新才会调用的回调函数
      this.$nextTick(() => {
        this.$refs.nameInp.focus()
      })
    },
    // 点击修改名字确认的事件
    async saveName () {
      // 发请求修改用户名
      await editUserInfoAPI({
        name: this.editName
      })
      // 请求发完后就把本地的数据做一个更新
      // 本地数据保存在vuex里，所以要通过vuex访问
      this.$store.commit('setUserInfo', {
        // 还要把以前的所有属性也放到这个对象中
        ...this.info,
        // 让name变成修改后的name
        name: this.editName
      })
    },

    // 点击男或女触发的事件
    async changeGender (gender) {
      // 发起请求修改用户性别
      await editUserInfoAPI({
        gender
      })
      // 把修改的数据保存到vuex中
      this.$store.commit('setUserInfo', {
        ...this.info,
        gender
      })
      // 修改完后弹出层隐藏
      this.genderShow = false
    },

    // 点击生日cell触发的事件
    birthdayHappy () {
      this.genderDay = true
      // 把当前用户的生日给生日选择器
      this.currentDate = new Date(this.info.birthday)
    },
    // 修改生日的确认事件
    async changeBirth () {
      // 发起请求给服务器修改生日数据
      // 因为服务器要的是字符串类型数据，而currentDate是一个日期对象
      // 所以我们需要把日期对象转换为字符串
      const birthday = moment(this.currentDate).format('YYYY-MM-DD')
      await editUserInfoAPI({
        birthday
      })
      // 把修改的数据保存到vuex中
      this.$store.commit('setUserInfo', {
        ...this.info,
        birthday
      })
      // 修改完成后隐藏生日选择器
      this.genderDay = false
    },

    // 选择完文件调用的参数
    // 参数file是选的文文件对象
    afterRead (file) {
      // 此时可以自行将文件上传至服务器
      console.log(file)
      // 显示裁剪容器
      this.cropShow = true
      // 把选中的插件交给裁剪插件去显示
      this.cropImg = file.content
    },
    // 裁剪按钮的点击事件
    doCrop () {
      // 调用插件的裁剪功能得到裁剪结果
      this.$refs.cropper.getCropBlob(async data => {
        // 参数data是得到裁剪后的blob对象
        // 发起请求传递给服务器
        // 调用这个接口要上传图片，但是ajax不能直接传递图片。ajax要想上传文件，需要利用FormData对象
        let fm = new FormData()
        fm.append('photo', data)
        let res = await editPhotoAPI(fm)
        // console.log(res);
        // 上传成功后，把数据更新到vuex
        this.$store.commit('setUserInfo',{
          ...this.info,
          photo: res.data.data.photo
        })
        // 隐藏裁剪容器
        this.cropShow = false
      })
    }
  },
  created () {
    this.$store.dispatch('reqUserInfo')
  },
  computed: {
    // 相当于给state里的userInfo起了别名叫info
    info () {
      return this.$store.state.userInfo
    }
  }
}
</script>

<style scoped lang="less">
.avatar_box {
  height: 132px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}
.ipt {
  border: 1px solid #eee;
}
.pop {
  height: 136px;
}
.pic-uploader {
  position: absolute;
  width: 100%;
  height: 100%;
  ::v-deep {
    .van-uploader__wrapper {
      width: 100%;
      height: 100%;
      .van-uploader__upload {
        width: 100%;
        height: 100%;
        margin: 0;
        // 不能让上传文件的组件挡住头像，还要在点击时有反应
        opacity: 0;
      }
    }
  }
}
.crop-box {
  // 使用固定定位，此时参照的是文档位置
  position: fixed;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  .van-button {
    position: absolute;
    bottom: 0;
    left: 0;
    // 找到第二个按钮
    &:nth-of-type(2) {
      // 让left恢复默认值
      left: auto;
      right: 0;
    }
  }
}
</style>
